#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

// 计算f(x)的阶乘
int calculate_fx(int x) {
    if (x == 1) return 1;
    return x * calculate_fx(x - 1);
}

// 计算f(y)的斐波那契数列
int calculate_fy(int y) {
    if (y == 1 || y == 2) return 1;
    return calculate_fy(y - 1) + calculate_fy(y - 2);
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <x> <y>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    int x = atoi(argv[1]);
    int y = atoi(argv[2]);

    // 创建四个管道：fx输入/输出，fy输入/输出
    int fx_in[2], fx_out[2], fy_in[2], fy_out[2];
    if (pipe(fx_in) || pipe(fx_out) || pipe(fy_in) || pipe(fy_out)) {
        perror("pipe creation failed");
        exit(EXIT_FAILURE);
    }

    // 创建计算f(x)的子进程
    pid_t pid_fx = fork();
    if (pid_fx == 0) {
        close(fx_in[1]);   // 关闭写端
        close(fx_out[0]);  // 关闭读端

        int val;
        read(fx_in[0], &val, sizeof(val));
        int result = calculate_fx(val);
        write(fx_out[1], &result, sizeof(result));

        close(fx_in[0]);
        close(fx_out[1]);
        exit(EXIT_SUCCESS);
    }

    // 创建计算f(y)的子进程
    pid_t pid_fy = fork();
    if (pid_fy == 0) {
        close(fy_in[1]);   // 关闭写端
        close(fy_out[0]);  // 关闭读端

        int val;
        read(fy_in[0], &val, sizeof(val));
        int result = calculate_fy(val);
        write(fy_out[1], &result, sizeof(result));

        close(fy_in[0]);
        close(fy_out[1]);
        exit(EXIT_SUCCESS);
    }

    // 主进程
    close(fx_in[0]);  // 关闭读端
    close(fx_out[1]); // 关闭写端
    close(fy_in[0]);
    close(fy_out[1]);

    // 发送参数给子进程
    write(fx_in[1], &x, sizeof(x));
    write(fy_in[1], &y, sizeof(y));
    close(fx_in[1]);
    close(fy_in[1]);

    // 接收计算结果
    int res_fx, res_fy;
    read(fx_out[0], &res_fx, sizeof(res_fx));
    read(fy_out[0], &res_fy, sizeof(res_fy));
    close(fx_out[0]);
    close(fy_out[0]);

    printf("f(%d,%d) = %d + %d = %d\n", x, y, res_fx, res_fy, res_fx + res_fy);

    // 等待子进程结束
    waitpid(pid_fx, NULL, 0);
    waitpid(pid_fy, NULL, 0);

    return EXIT_SUCCESS;
}
